module tn256_pioneer_v1(
	input       clk50m   ,
	input       rst_n    ,
	input       KEY2     ,// 按键，打开或关闭伪彩色算法
	input       KEY3     ,// 按键，单点校正触发
	//TN256模组接口
	input [7:0] D  ,
	input       PC ,//TN256模组的像素时钟
	input       HS ,//TN256模组的行同步信号，高有效
	input       VS ,//TN256模组的场同步信号，高有效
	output      MC ,//TN256模组的工作时钟
	output      RST,//TN256模组的复位，低有效
	output      ADR,//TN256模组的 I2C接口使能，高有效 / 挡片使能，低有效
	output      SCL,//TN256模组I2C接口时钟
	inout       SDA,//TN256模组I2C接口数据
//VGA接口
    output  wire            vga_hs      ,  //行同步信号
    output  wire            vga_vs      ,  //场同步信号
    output  wire    [15:0]  vga_rgb     ,  //红绿蓝三原色输出 
	//SDRAM Port
	output                      sdram_clk,         //sdram clock
	output                      sdram_cke,         //sdram clock enable
	output                      sdram_cs_n,        //sdram chip select
	output                      sdram_we_n,        //sdram write enable
	output                      sdram_cas_n,       //sdram column address strobe
	output                      sdram_ras_n,       //sdram row address strobe
	output[1:0]                 sdram_dqm,         //sdram data enable
	output[1:0]                 sdram_ba,          //sdram bank address
	output[12:0]                sdram_addr,        //sdram address
	inout[15:0]                 sdram_dq           //sdram data
);
wire pll_lock_w;
wire [13:0] data_w;
wire hsync_w,vsync_w,de_w;
wire clk_25m;
wire clk_ref,clk_refout;//sdram控制器100M工作时钟、给SDRAM芯片的100M时钟
assign sdram_dqm = 2'b00;
assign RST = rst_n;//pll_lock_w;
sys_pll u_sys_pll_0 (
	.areset(!rst_n    ),
	.inclk0(clk50m    ),
	.c0    (MC        ),
	.c1    (clk_25m ),//25MHz For VGA
	.c2    (clk_ref ),
	.c3    (clk_refout ),
	.locked(pll_lock_w)
	);
//按键控制模块
wire  [3:0] pulse;
wire  [3:0] sw;
key_pulse u_key_pulse(
       .clk(PC),
	   .rst_n(rst_n),
	   .key({KEY3,KEY2,2'b11}),
	   .pulse(pulse)
);
wire falsecolor_en;
pulse_cnt#(
	.DWIDTH(1)
)u_pulse_cnt_0(
    .clk  (PC),
	.rst_n(rst_n),
	.pulse(pulse[2]),
	.ocnt (falsecolor_en)
);
//单点校正和挡片控制模块
wire [1:0] motor_w;
wire       motor_en_w;
wire       img_store_trig_w;
wire       img_store_done_w;
leaf_ctrl u_leaf_ctrl_0(
	.clk           (PC              ),//使用探测器输出的PC作为clk，频率12MHz
	.rst_n         (rst_n           ),
	.leaf_trig     (pulse[3]        ),//持续1个clk高电平即触发一次挡片校正
	.o_motor       (motor_w         ),
	.o_motor_en    (motor_en_w      ),//挡片控制使能信号，高有效
	.img_store_trig(img_store_trig_w),
	.img_store_done(img_store_done_w)
);
TN256_I2C_top u_TN256_I2C_top_0(
	.clk50M(clk50m),
	.irst_n(rst_n && sdram_init_done),
	.i_motor_en(motor_en_w),//(~k3),
	.i_motor(motor_w),//({!k2,1'b0}),//({!k2,!k1}),
	.sda   (SDA),
	.sclk  (SCL),
	.ALSB  (ADR) //ADR
			  );
//对TN256的接口进行打拍
wire HS_w0,VS_w0;
wire [7:0] D_w0;
shift_regs#(
.DWIDTH(10),//数据位宽
.DELAY_DUTY(3)//延迟的时钟周期数，最小是1
)u_shift_regs_0(
    .clk(PC),
	.rst_n(rst_n),
	.idata({HS,VS,D}),
	.odata({HS_w0,VS_w0,D_w0})
);
tn256_data_cvnt u_tn256_data_cvnt_0(
	.clk  (PC     ),
	.rst_n(rst_n  ),
	.hs   (HS_w0     ),
	.vs   (VS_w0     ),
	.idata(D_w0      ),
	.odata(data_w ),
	.hsync(hsync_w),
	.vsync(vsync_w),
	.de   (de_w   )
);
wire [13:0] data_w0;
wire valid_w0,ready_w0,sop_w0,eop_w0;
native2ast_top#(
.WIDTH (256),  //视频宽度
.HEIGHT(200),  //视频高度
.DWIDTH(14 )   //数据位宽
	)u_native2ast_top_0(
    .clk         (PC        ),
	.rst_n       (rst_n     ),
	.pre_vsync   (vsync_w   ),
	.pre_hsync   (hsync_w   ),
	.pre_valid   (de_w      ),
	.pre_data    (data_w    ),
	.almost_full (),
    .source_ready(ready_w0),
	.source_valid(valid_w0),
	.source_eop  (eop_w0),
	.source_sop  (sop_w0),
	.source_data (data_w0) 
    );

//存图模块
wire [15:0] wr1_data;
wire        wr1_wrreq;
wire [15:0] rd1_data;
wire        rd1_rdreq,rd1_empty;
wire        RD2_EMPTY;
assign ready_w0 = ready_w1;//
fifo_port_img_wr#(
.DWITH(16)      //图像数据位宽
	)u_fifo_port_img_wr_0(
	.clk    (PC),
	.rst_n  (rst_n),
	.wr_trig(img_store_trig_w),//(pulse[3]),
	.wr_done(img_store_done_w),//wr_done信号作为挡片开启的触发信号
	//视频接口
	.sink_sop  (sop_w0  ),
	.sink_eop  (eop_w0  ),
	.sink_valid(valid_w0),
	.sink_data (data_w0 ),	 
	//写FIFO接口
	.fifo_wr   (wr1_wrreq),
	.fifo_data (wr1_data )
	);

wire [13:0] data_w1;
wire valid_w1,sop_w1,eop_w1,ready_w1;
one_point#(
	.P_ADD_NUM(8192),//减去背景可能出来负数，加上偏置规避负数
	.P_DGC(10'd256)  //数字增益，P_DGC除以256就是实际的增益系数
)u_one_point_0(
	.i_clk			(PC   ),
	.i_rst_n		(rst_n),
		
	/******模块信号输入*******/
	.i_hsync		(sop_w0  ),
	.i_vsync		(eop_w0  ),
	.i_de			(valid_w0),
	.i_data			(data_w0 ),
		
	/*******sdram信号输入********/
	.o_RD1			(rd1_rdreq),
	.i_RD1_DATA		(rd1_data ),
	
	
	/*********单点结果输出***********/
	.o_hs			(sop_w1),
	.o_vs			(eop_w1),
	.o_de			(valid_w1),
	.o_data	        (data_w1)
);

//AST不带反压信号转带反压信号（ready）
ast_readylatency_adapt#(
	.DWIDTH       (12), 
	.WIDTH        (256 ), 
	.HEIGHT       (200), 
	.FIFO_DEPTH   (1024  ) //FIFO的深度，必须为2的整数次方倍并且大于32
)u_ast_readylatency_adapt_0(
	.clk         (PC         ),
	.rst_n       (rst_n       ),
	.sink_sop    (sop_w1      ),
	.sink_valid  (valid_w1    ),
	.sink_data   (data_w1[13:2]),
	.sink_eop    (eop_w1      ), 
	.sink_ready  (ready_w1  ),             
	.source_sop  (sop_w2  ),
	.source_valid(valid_w2),
	.source_data (data_w2 ),
	.source_eop  (eop_w2  ),
	.source_ready(ready_w2)
);

//直方图均衡算法模块
wire [11:0] data_w2;
wire valid_w2,ready_w2,sop_w2,eop_w2;
/*
assign valid_w3 = valid_w2;
assign sop_w3   = sop_w2;
assign eop_w3   = eop_w2;
assign data_w3  = data_w2;
assign ready_w2 = ready_w3;
*/
hist_equ_top #(
	.WIDTH(256),
	.HEIGHT(200)
)u_hist_equ_top_0(
	 .clk(PC),
	 .rst_n(rst_n),
	 .proc_en(1'b1),
	 .sink_sop(sop_w2),
	 .sink_valid(valid_w2),
	 .sink_data(data_w2),
	 .sink_eop(eop_w2),
	 .sink_ready(ready_w2),
	 .source_sop(sop_w3),
	 .source_valid(valid_w3),
	 .source_data(data_w3),
	 .source_eop(eop_w3),
	 .source_ready(ready_w3)
	 );

//放大模块 256*200-->480*320
//图像数据编码
wire [11:0] data_w3;
wire valid_w3,ready_w3,sop_w3,eop_w3;
wire [7:0] data_w4;
wire valid_w4,ready_w4,sop_w4,eop_w4;
dmk_encode #(
	.DATA_WIDTH(8),
	.DATA_BITS(8),
	.DATA_PLANES(1))
u_dmk_encode_0 (
	.clk(PC),
	.rst_n(rst_n),

	.video_width(256),
	.video_height(200),
	.video_interlaced(4'h0),

	.din_data(data_w3[11:4]),
	.din_valid(valid_w3),
	.din_ready(ready_w3),
	.din_startofpacket(sop_w3),
	.din_endofpacket(eop_w3),

	.dout_data(data_w4),
	.dout_valid(valid_w4),
	.dout_ready(ready_w4),
	.dout_startofpacket(sop_w4),
	.dout_endofpacket(eop_w4)
);
wire [7:0] data_w5;
wire valid_w5,ready_w5,sop_w5,eop_w5;
wire [7:0] data_w6;
wire valid_w6,ready_w6,sop_w6,eop_w6;
scaller u_scaller_0 (
		.clk_clk(PC),              //    clk.clk
		.reset_reset_n(rst_n),        //  reset.reset_n
		.sink_data(data_w4),            //   sink.data
		.sink_valid(valid_w4),           //       .valid
		.sink_startofpacket(sop_w4),   //       .startofpacket
		.sink_endofpacket(eop_w4),     //       .endofpacket
		.sink_ready(ready_w4),           //       .ready
		.source_data(data_w5),          // source.data
		.source_valid(valid_w5),         //       .valid
		.source_startofpacket(sop_w5), //       .startofpacket
		.source_endofpacket(eop_w5),   //       .endofpacket
		.source_ready(ready_w5)          //       .ready
	);
dmk_decode #
(
	.DATA_WIDTH(8),
    .COLOR_BITS(8),
	.COLOR_PLANES(1)
)
u_dmk_decode_0(
	.clk(PC),
	.rst_n(rst_n),
	.din_data(data_w5),
	.din_valid(valid_w5),
	.din_ready(ready_w5),
	.din_startofpacket(sop_w5),
	.din_endofpacket(eop_w5),

	.im_width(),
	.im_height(),
	.im_interlaced(),
	
	.dout_data(data_w6),
	.dout_valid(valid_w6),
	.dout_ready(ready_w6),
	.dout_startofpacket(sop_w6),
	.dout_endofpacket(eop_w6)
);
//伪彩色算法模块
wire [23:0] data_w7;
wire valid_w7,ready_w7,sop_w7,eop_w7;	
falsecolor u_falsecolor_0(
	 .clk(PC),
	 .rst_n(rst_n),
	 .proc_en(falsecolor_en),
	 //sink 
	 .sink_sop(sop_w6),
	 .sink_valid(valid_w6),
	 .sink_data(data_w6),//原始数据
	 .sink_eop(eop_w6),
	 .sink_ready(ready_w6),
	 //source
	 .source_sop(sop_w7),
	 .source_valid(valid_w7),
	 .source_data(data_w7),//伪彩色的结果
	 .source_eop(eop_w7),
	 .source_ready(1'b1)
);	
//
//拍照存图模块
wire [15:0] wr2_data;
wire        wr2_wrreq;
wire [15:0] rd2_data;
wire        rd2_rdreq,rd2_empty;
assign wr2_data  = {data_w7[23:19],data_w7[15:10],data_w7[7:3]};
assign wr2_wrreq = valid_w7;
/*
wire        rd_trig_w;//拍照数据读出
fifo_port_img_wr#(
.DWITH(16)      //图像数据位宽
	)u_fifo_port_img_wr_1(
	.clk    (PC),
	.rst_n  (rst_n),
	.wr_trig(1),//↑按键 拍照
	.wr_done(rd_trig_w),//wr_done信号作为读图的触发信号
	//视频接口
	.sink_sop  (sop_w7  ),
	.sink_eop  (eop_w7  ),
	.sink_valid(valid_w7),
	.sink_data ({data_w7[23:19],data_w7[15:10],data_w7[7:3]} ),	 
	//写FIFO接口
	.fifo_wr   (wr2_wrreq),
	.fifo_data (wr2_data )
	);
*/
//4port SDRAM控制器模块
	Sdram_Control_4Port Sdram_Control_4Port(
		//	HOST Side
		.REF_CLK(clk_ref),
		.OUT_CLK(clk_refout),
		.RESET_N(rst_n && pll_lock_w),	//复位输入，低电平复位
		//.SDRAM_INIT_DONE(sdram_init_done),
		//	FIFO Write Side 1
		.WR1_DATA(wr1_data),			//写入端口1的数据输入端，16bit
		.WR1(wr1_wrreq),					//写入端口1的写使能端，高电平写入
		.WR1_ADDR(0),			//写入端口1的写起始地址
		.WR1_MAX_ADDR(256*200),		//写入端口1的写入最大地址
		.WR1_LENGTH(256),			//一次性写入数据长度
		.WR1_LOAD(~rst_n),			//写入端口1清零请求，高电平清零写入地址和fifo
		.WR1_CLK(PC ),				//写入端口1 fifo写入时钟
		.WR1_FULL(),			//写入端口1 fifo写满信号
		.WR1_USE(),				//写入端口1 fifo已经写入的数据长度

		//	FIFO Write Side 2
		.WR2_DATA(wr2_data),			//写入端口2的数据输入端，16bit
		.WR2(wr2_wrreq),//(wr1_wrreq),					//写入端口2的写使能端，高电平写入
		.WR2_ADDR(480*320),			//写入端口2的写起始地址
		.WR2_MAX_ADDR(480*320*2),		//写入端口2的写入最大地址
		.WR2_LENGTH(256),			//一次性写入数据长度
		.WR2_LOAD(~rst_n),			//写入端口2清零请求，高电平清零写入地址和fifo
		.WR2_CLK(PC),				//写入端口2 fifo写入时钟
		.WR2_FULL(),			//写入端口2 fifo写满信号
		.WR2_USE(),				//写入端口2 fifo已经写入的数据长度

		//	FIFO Read Side 1
		.RD1_DATA(rd1_data),			//读出端口1的数据输出端，16bit
		.RD1(rd1_rdreq),					//读出端口1的读使能端，高电平读出
		.RD1_ADDR(0),			//读出端口1的读起始地址
		.RD1_MAX_ADDR(256*200),		//读出端口1的读出最大地址
		.RD1_LENGTH(256),			//一次性读出数据长度
		.RD1_LOAD(~rst_n),			//读出端口1 清零请求，高电平清零读出地址和fifo
		.RD1_CLK(PC),				//读出端口1 fifo读取时钟
		.RD1_EMPTY(rd1_empty),			//读出端口1 fifo读空信号
		.RD1_USE(),				//读出端口1 fifo已经还可以读取的数据长度

		//	FIFO Read Side 2
		.RD2_DATA(rd2_data),			//读出端口2的数据输出端，16bit
		.RD2(rd2_rdreq),//(~RD2_EMPTY && (rd1_rdreq || wr1_wrreq)),					//读出端口2的读使能端，高电平读出
		.RD2_ADDR(480*320),			//读出端口2的读起始地址
		.RD2_MAX_ADDR(480*320*2),		//读出端口2的读出最大地址
		.RD2_LENGTH(256),			//一次性读出数据长度
		.RD2_LOAD(~rst_n),			//读出端口2清零请求，高电平清零读出地址和fifo
		.RD2_CLK(clk_25m),				//读出端口2 fifo读取时钟
		.RD2_EMPTY(rd2_empty),			//读出端口2 fifo读空信号
		.RD2_USE(),				//读出端口2 fifo已经还可以读取的数据长度

		//	SDRAM Side
		
		.SA(sdram_addr),		//SDRAM 地址线，
		.BA(sdram_ba),		//SDRAM bank地址线
		.CS_N(sdram_cs_n),		//SDRAM 片选信号
		.CKE(sdram_cke),		//SDRAM 时钟使能
		.RAS_N(sdram_ras_n),	//SDRAM 行选中信号
		.CAS_N(sdram_cas_n),	//SDRAM 列选中信号
		.WE_N(sdram_we_n),		//SDRAM 写请求信号
		.DQ(sdram_dq),		//SDRAM 双向数据总线
		.SDR_CLK(sdram_clk),
		.DQM(),		//SDRAM 数据总线高低字节屏蔽信号
		.Sdram_Init_Done(sdram_init_done)
	);
//------------- vga_ctrl_inst -------------
wire [15:0] pix_data_w;
reg rd2_rdreq_r;
assign pix_data_w = rd2_rdreq_r?rd2_data:16'hffff;
always@(posedge clk_25m or negedge rst_n)
if(!rst_n)
    rd2_rdreq_r <= 1'b0;
else
    rd2_rdreq_r <= rd2_rdreq;
vga_ctrl    vga_ctrl_inst
(
    .vga_clk        (clk_25m    ),  //输入工作时钟,频率25MHz
    .sys_rst_n      (rst_n      ),  //输入复位信号,低电平有效
    .pix_data       (pix_data_w ),  //待显示数据输入

    .pix_data_req   (rd2_rdreq  ),  //数据请求信号
    .hsync          (vga_hs     ),  //输出行同步信号
    .vsync          (vga_vs     ),  //输出场同步信号
    .rgb            (vga_rgb    )   //输出像素信息
);
endmodule 